/*
 * StartApplication.java
 *
 * Created on Jul 14, 2008 11:55:00 AM;
 */

package org.sunspotworld;

import com.sun.spot.core.resources.transducers.ISwitch;
import com.sun.spot.core.resources.transducers.ITriColorLED;
import com.sun.spot.core.resources.transducers.LEDColor;
import com.sun.spot.core.util.Utils;
import com.sun.spot.edemo.EDemoBoard;

import java.util.Enumeration;
import java.util.Vector;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;

/**
 * The startApp method of this class is called by the VM to start the
 * application.
 * 
 * The manifest specifies this class as MIDlet-1, which means it will
 * be selected for execution.
 */
public class StartApplication extends MIDlet {

    private ISwitch sw1 = EDemoBoard.getInstance().getSwitches()[EDemoBoard.SW1];
    private ISwitch sw2 = EDemoBoard.getInstance().getSwitches()[EDemoBoard.SW2];
    private static ITriColorLED [] leds = EDemoBoard.getInstance().getLEDs();
    
    public static final int SECONDS = 1000;
    public static final int MAX_SLEEP_TIME = 3*SECONDS;
    private boolean useSync = false;
    private static Buffer buffer = new Buffer();
    
    private static final LEDColor[] COLORS = {LEDColor.BLUE, LEDColor.CHARTREUSE, LEDColor.CYAN, LEDColor.GREEN, LEDColor.MAGENTA, LEDColor.MAUVE, LEDColor.ORANGE, LEDColor.PUCE, LEDColor.RED, LEDColor.TURQUOISE, LEDColor.WHITE, LEDColor.YELLOW};
    private int colorIndex = 0;
    private Vector myThreads = new Vector();
    
    protected void startApp() throws MIDletStateChangeException {
        while(true) {
            if (sw1.isClosed()) {
                Utils.sleep(50);
                if (sw2.isClosed()) {
                    switchSynched();
                } else {
                    addProducer();
                }
                while(sw1.isClosed()) {
                    Utils.sleep(100);
                }
            } else if(sw2.isClosed()) {
                Utils.sleep(50);
                if (sw1.isClosed()) {
                    switchSynched();
                } else {
                    addConsumer();
                }
                while (sw2.isClosed()) {
                    Utils.sleep(100);
                }
            }
        }
    }
    
    private void addProducer() {
        if (colorIndex==COLORS.length) {
            return;
        }
        Thread newThread;
        if (useSync) {
            newThread = new SynchedProducer(COLORS[colorIndex], buffer);
        } else {
            newThread = new Producer(COLORS[colorIndex], buffer);
        }
        myThreads.addElement(newThread);
        colorIndex++;
        newThread.start();
    }
    
    private void addConsumer() {
        Thread newThread;
        if (useSync) {
            newThread = new SynchedConsumer(buffer);
        } else {
            newThread = new Consumer(buffer);
        }
        myThreads.addElement(newThread);
        colorIndex++;
        newThread.start();
    }
    
    private void switchSynched() {
        useSync = !useSync;
        buffer.shutdown();
        Enumeration en = myThreads.elements();
        while (en.hasMoreElements()) {
            try {
                MyThread next = (MyThread) en.nextElement();
                next.stopRunning();
                next.join();
            } catch (InterruptedException ex) {
                //ex.printStackTrace();
            }
        }
        myThreads.removeAllElements();
        buffer.restart();
    }
    
    protected void pauseApp() {
        // This is not currently called by the Squawk VM
    }

    /**
     * Called if the MIDlet is terminated by the system.
     * I.e. if startApp throws any exception other than MIDletStateChangeException,
     * if the isolate running the MIDlet is killed with Isolate.exit(), or
     * if VM.stopVM() is called.
     * 
     * It is not called if MIDlet.notifyDestroyed() was called.
     *
     * @param unconditional If true when this method is called, the MIDlet must
     *    cleanup and release all resources. If false the MIDlet may throw
     *    MIDletStateChangeException  to indicate it does not want to be destroyed
     *    at this time.
     */
    protected void destroyApp(boolean unconditional) throws MIDletStateChangeException {
        for (int i = 0; i < 8; i++) {
            leds[i].setOff();
        }
    }
}
